package dirfile

import (
	"bufio"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
)

//判断文件或目录是否存在
//参数：path文件或目录路径
//返回
//第一个 true:存在 false:不存在
//第二个 err 错误（非不存在错误）
func FileDirExist(path string) (bool, error) {
	_, err := os.Stat(path)

	if os.IsNotExist(err) {
		return false, nil
	}
	if err == nil {
		return true, nil
	}
	return false, err
}

//从指定目录，递归查找某些后缀文件，白名单和黑名单，若白名单、黑名单重复，黑名单优先
//参数
//dirPath:指定目录
//files：文件列表
//targets：后缀白名单
//except：后缀黑名单
//返回错误
func GetAllFiles(dirPath string,files *[]string,targets *[]string,except *[]string) error{
	file,err := os.Stat(dirPath)
	if err != nil{
		return err
	}else{
		if !file.IsDir(){
			return errors.New("dirPath is not a directory")
		}
	}
	entry,err := ioutil.ReadDir(dirPath)
	if err != nil{
		return err
	}
	sep := string(os.PathSeparator)
	// 遍历指定目录
	for _,f := range entry{
		tmp := dirPath+sep+f.Name()
		//标记是否不需要保存
		var flag  = false
		for _,suffix := range *except {
			if strings.HasSuffix(tmp,suffix){
				flag = true
				break
			}
		}
		if flag{
			continue
		}
		//-------目录，递归遍历---------
		if f.IsDir(){
			err = GetAllFiles(tmp,files,targets,except)
			if err != nil{
				return err
			}
		}else {
			for _,suffix := range *targets {
				if strings.HasSuffix(tmp,suffix){
					*files = append(*files,tmp)
					break
				}
			}
		}
	}
	return nil
}

// 白名单 黑明单 形式， 黑名单优先。含黑名单任意一个的即排除 含白名单任意一个的即保留
//path：文件路径
//targets：白名单
//except：黑名单
//返回结果，字符串切片及错误，切片格式：行数 内容
func FileContainsStr(path string,targets ,except *[]string) ([]string,error) {
	f, err := os.Open(path)
	if err != nil {
		return nil,err
	}
	defer f.Close()
	input := bufio.NewScanner(f)
	line,res := 0,make([]string,0)
	loop:
	for input.Scan() {
		line++
		info:=input.Text()
		// black list
		for _,s := range *except{
			if strings.Contains(info,s){
				continue loop
			}
		}
		// white list
		ok := false
		for _,s := range *targets{
			if strings.Contains(info,s){
				ok = true
				break
			}
		}
		if ok{
			res = append(res,fmt.Sprintf("%d %s",line,info))
		}
	}
	return res,nil
}